package com.zl.codereview;

import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeRegistry;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.SimpleToolWindowPanel;
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.JBColor;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBPanel;
import com.intellij.ui.components.JBScrollPane;
import com.zl.codereview.git.GitService;
import com.zl.codereview.git.model.ProjectQuery;
import com.zl.codereview.git.model.ReviewProjectResp;
import com.zl.codereview.git.model.TreeComponent;
import com.zl.codereview.git.swing.ReviewTreePanel;
import com.zl.codereview.review.CodeReviewProject;
import com.zl.codereview.review.ReviewContent;
import com.zl.codereview.review.ReviewEntity;
import com.zl.codereview.util.ThreadExecutors;
import com.zl.codereview.util.ObjectUtils;

import javax.swing.*;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultTreeCellRenderer;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

public class ReviewView extends SimpleToolWindowPanel implements MouseListener, KeyListener {

    private JButton button;

    private JBPanel headPanel;

    private ReviewTreePanel bodyPanel;

    private JBPanel detailPanel;

    private JBScrollPane scrollPane;

    private JBScrollPane bodyScrollPane;

    private boolean searchActive = false;

    private Project project;

    private VirtualFile nowFile;

    private ProjectQuery query = new ProjectQuery();

    private GitService gitService = GitService.getInstance();

    public static final String ALL_REVIEW = "全部";
    public static final String MY_APPLY_REVIEW = "我发起的";
    public static final String ASSIGNED_TO_ME = "指派给我的";
    private String comboboxValue = "";


    public ReviewView(Project project){
        super(true,true);
        this.project = project;
        // 获取模块管理器
        this.setLayout(new BorderLayout());
        this.headPanel = new JBPanel();
        FlowLayout flowLayout = new FlowLayout();
        flowLayout.setAlignment(FlowLayout.LEFT);
        this.headPanel.setLayout(flowLayout);

        //文本框
        ComboBox<String> comboBox = initComboBox();
        comboBox.setSize(120,25);
        comboBox.setOpaque(true);
        comboBox.setBackground(JBColor.background());
        this.headPanel.add(comboBox);

        this.button = new JButton();
        this.button.setSize(60,25);
        this.button.setText("search");
        this.button.setOpaque(true);
        this.button.setBackground(JBColor.background());
        this.headPanel.add(this.button);

        this.add(headPanel,BorderLayout.NORTH);

        //bodyPanel
        initBodyPanel();

        detailPanel = new JBPanel();
        JBScrollPane detailScroll = new JBScrollPane(detailPanel);
        this.detailPanel.setVisible(true);


        Splitter splitter = new Splitter(true); // false 表示水平分割
        splitter.setFirstComponent(bodyScrollPane);
        splitter.setSecondComponent(detailScroll);
        splitter.setProportion(0.6F);
        this.add(splitter,BorderLayout.CENTER);

        this.button.addMouseListener(this);
        this.setVisible(true);
    }

    public void refresh(){
        refreshBodyPanel();
    }

    private ComboBox<String> initComboBox(){
        // 创建一个 ComboBox 的模型
        DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();

        // 添加选项
        model.addElement(ALL_REVIEW);
        model.addElement(MY_APPLY_REVIEW);
        model.addElement(ASSIGNED_TO_ME);
        // 创建 ComboBox 组件
        ComboBox<String> comboBox = new ComboBox<>(model);

        // 设置选择事件监听器
        comboBox.addActionListener(e -> {
            this.comboboxValue = (String) comboBox.getSelectedItem();
            new Thread(this::refreshBodyPanel).start();
        });
        return comboBox;
    }


    public void refreshBodyPanel(){
        if(searchActive){
            return;
        }
        searchActive = true;
        this.bodyPanel.setVisible(false);
        if(!ObjectUtils.isEmpty(scrollPane)){
            this.bodyPanel.remove(scrollPane);
        }
        this.bodyPanel.setVisible(true);
        JTree tree = loadJTree();
        if(tree == null){
            searchActive = false;
            return;
        }
        tree.setBorder(null);
        tree.setOpaque(true);

        scrollPane = new JBScrollPane(tree);
        scrollPane.setOpaque(true);
//        scrollPane.setPreferredSize(this.getSize());
        this.bodyPanel.add(scrollPane);
        this.scrollPane.setVisible(true);
        this.bodyPanel.setVisible(true);
        this.bodyPanel.stopWait();
        tree.addMouseListener(this);
        this.revalidate();
        searchActive = false;
        initJLabelDetail(new ArrayList<>());
    }

    private JTree loadJTree(){
        //代码信息
        ThreadExecutors threadExecutors = new ThreadExecutors();
        CompletableFuture aysnc = threadExecutors.aysnc(() -> {

            try {
                int operate = 0;
                if(MY_APPLY_REVIEW.equals(this.comboboxValue)){
                    operate = 1;
                }else if(ASSIGNED_TO_ME.equals(this.comboboxValue)){
                    operate = 2;
                }
                List<ReviewEntity> resps = gitService.getReviewEntity(this.project,operate);
                //组装树
                TreeComponent node = new TreeComponent(this.project.getName());
                node.setData(new ReviewProjectResp());
                createTreeNode(node, resps);
                JTree tree = new JTree(node);
                tree.setFont(new Font(null,Font.PLAIN,14));
                tree.setCellRenderer(new DefaultTreeCellRenderer() {
                    @Override
                    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
                        super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
                        if(value instanceof TreeComponent){
                            TreeComponent component = (TreeComponent) value;
                            Object data = component.getData();
                            if(data instanceof ReviewEntity){
                                ReviewEntity entity = (ReviewEntity) data;
                                List<CodeReviewProject> projectList = entity.getProjectList();
                                if(!ObjectUtils.isEmpty(projectList)){
                                    projectList.forEach(project -> {
                                        if(!ObjectUtils.isEmpty(project.getContentList())){
                                            project.getContentList().forEach(content -> {
                                                if(content.getStatus() == 1){
                                                    setForeground(JBColor.RED);
                                                }
                                            });
                                        }
                                    });
                                }
                            }
                            if(data instanceof CodeReviewProject) {
                                CodeReviewProject reviewProject = (CodeReviewProject) data;
                                boolean b = reviewProject.getContentList().stream().anyMatch(r -> r.getStatus() == 1);
                                if (b) {
                                    setForeground(JBColor.RED);
                                }
                            }
                        }
                        // 获取文件类型
                        String s = String.valueOf(value);
                        if(s.contains(".")) {
                            String prefix = s.substring(s.lastIndexOf(".")+1);
                            FileType fileType = FileTypeRegistry.getInstance().getFileTypeByExtension(prefix);
                            // 获取图标
                            if (!ObjectUtils.isEmpty(fileType) && !ObjectUtils.isEmpty(fileType.getIcon())) {
                                setIcon(fileType.getIcon());
                            }
                        }
                        ModuleManager moduleManager = ModuleManager.getInstance(project);
                        // 获取项目关联的 modules
                        Module[] modules = moduleManager.getModules();
                        for(Module module : modules){
                            if(s.equals(module.getName())){
                                Icon icon = ModuleType.get(module).getIcon();
                                if (!ObjectUtils.isEmpty(icon)) {
                                    setIcon(icon);
                                }
                                break;
                            }
                        }
                        return this;
                    }
                });
                //监听
                tree.addTreeSelectionListener(new TreeSelectionListener() {//添加listener
                    @Override
                    public void valueChanged(TreeSelectionEvent e) {
                        Object bean = ((TreeComponent) e.getNewLeadSelectionPath().getLastPathComponent()).getData();
                        if (bean instanceof CodeReviewProject) {
                            CodeReviewProject projectFile = (CodeReviewProject) bean;
                            VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByPath(projectFile.getPath());

                            FileEditorManager editorManager = FileEditorManager.getInstance(project);
                            if(!ObjectUtils.isEmpty(virtualFile)) {
                                nowFile = virtualFile;
                                editorManager.openFile(virtualFile, false);
                                List<ReviewContent> contentList = projectFile.getContentList();
                                initJLabelDetail(contentList);
                            }
                        }
                    }
                });
                this.bodyPanel.stopWait();
                return tree;
            }catch (Exception e){
                this.bodyPanel.stopWait();
                return null;
            }
        });
        this.bodyPanel.startWait();
        return (JTree) threadExecutors.get(aysnc);
    }

    private void initJLabelDetail(List<ReviewContent> contentList){
        int rows = 10;
        if(contentList.size() > 10){
            rows = contentList.size();
        }
        GridLayout gridLayout = new GridLayout(rows,1);
        detailPanel.setLayout(gridLayout);
        detailPanel.removeAll();
        for(ReviewContent content : contentList){
            String value = content.getNumber()+"--->"+content.getAuthor();
            JBLabel label = new JBLabel(value);
            label.setName(value);
            label.setFont(new Font(null,Font.PLAIN,16));
            label.setForeground(JBColor.BLUE);
            if(content.getStatus() == 1){
                label.setForeground(JBColor.RED);
            }else{
                label.setForeground(new JBColor(new Color(6, 125, 23), new Color(6, 125, 23)));
            }
            this.detailPanel.add(label);
            label.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if(nowFile == null){
                        return;
                    }
                    int lineStartNum = content.getNumber();
                    if(lineStartNum > 0){
                        lineStartNum = lineStartNum -1;
                    }
                    int lineEndNum = content.getNumber();
                    if(lineEndNum > 0){
                        lineEndNum = lineEndNum - 1;
                    }
                    FileEditorManager editorManager = FileEditorManager.getInstance(project);
                    TextEditor textEditor = (TextEditor) editorManager.getSelectedEditor(nowFile);
                    if (textEditor != null) {
                        Editor editor = textEditor.getEditor();
                        editor.getScrollingModel().scrollTo(editor.offsetToLogicalPosition(editor.getDocument().getLineStartOffset(lineStartNum - 1)), ScrollType.CENTER_UP);
                        int lineStart = editor.getDocument().getLineStartOffset(lineStartNum);
                        int lineEnd = editor.getDocument().getLineEndOffset(lineEndNum);
                        editor.getSelectionModel().setSelection(lineStart, lineEnd);
                    }
                }
            });
        }

        detailPanel.revalidate();
        detailPanel.repaint();

    }



    private void createTreeNode(TreeComponent component, List<ReviewEntity> projectResps){
        if(ObjectUtils.isEmpty(projectResps)){
            return;
        }
        for(ReviewEntity resp : projectResps){
            TreeComponent node = new TreeComponent(resp.getName());
            node.setData(resp);
            createTreeFileNode(node,resp.getProjectList());
            component.add(node);
        }
    }

    private void createTreeFileNode(TreeComponent component, List<CodeReviewProject> files){
        if(ObjectUtils.isEmpty(files)){
            return;
        }
        for(CodeReviewProject file : files){
            TreeComponent node = new TreeComponent(file.getFileName());
            node.setData(file);
            component.add(node);
        }
    }

    private void initBodyPanel(){
        this.bodyPanel = new ReviewTreePanel();
        BorderLayout layout = new BorderLayout();
        this.bodyPanel.setLayout(layout);
        this.bodyPanel.setVisible(true);
        this.bodyScrollPane = new JBScrollPane(this.bodyPanel);
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {

    }

    @Override
    public void keyReleased(KeyEvent e) {
        int keyCode = e.getKeyCode();
        if(10 == keyCode){
            Object source = e.getSource();
            if(source instanceof ComboBox) {
                new Thread(this::refreshBodyPanel).start();
            }
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        Object source = e.getSource();
        if(source == this.button){
            new Thread(this::refreshBodyPanel).start();
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {

    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }
}
